package com.attcatstudy.cas;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;

/**
 * @author attcat
 * ---做一个有趣的程序员
 * @date 2022-11-02 21:00
 * @description
 * 在并发量较低的环境下，线程冲突的概率比较小，自旋的次数不会很多。但是，高并发环境下，
 * N个线程同时进行自旋操作，
 * 会出现大量失败并不断自旋的情况，此时AtomicLong的自旋会成为 瓶颈。
 * 这就是LongAdder引入的初衷——解决高并发环境下AtomicInteger， AtomicLong的自旋瓶颈问题
 */
public class LongAdderTest {
    public static void main(String[] args) throws InterruptedException {

        testAtomicLongVSLongAdder(10, 10000);
        System.out.println("==================");
         testAtomicLongVSLongAdder(10, 200000);
         System.out.println("==================");
         testAtomicLongVSLongAdder(100, 200000);
        System.out.println("==================");
        testAtomicLongVSLongAdder(100, 2000000);

    }
    static void testAtomicLongVSLongAdder(final int threadCount, final int times) throws InterruptedException {


        long start = System.currentTimeMillis();
        testLongAdder(threadCount, times);
        long end = System.currentTimeMillis()-start;
        System.out.println("条件>>>>>>线程数:" + threadCount + ", 单线程操作计数" + times);
        System.out.println("结果>>>>>>LongAdder方式增加计数" + (threadCount * times) + "次,共计耗时:" + end);

        long start2 = System.currentTimeMillis();
        testAtomicLong(threadCount, times);
        long end2 = System.currentTimeMillis()-start2;
        System.out.println("条件>>>>>>线程数:" + threadCount + ", 单线程操作计数" + times);
        System.out.println("结果>>>>>>AtomicLong方式增加计数" + (threadCount * times) + "次,共计耗时:" + end2);


    }




    //用tomicLong
    static void testAtomicLong(final int threadCount, final int times) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(threadCount);
        AtomicLong atomicLong = new AtomicLong();
        for(int i = 0; i < threadCount; i++){
            new Thread(()->{
                for(int j=0;j<times;j++){
                     atomicLong.incrementAndGet();}
                countDownLatch.countDown();
            }).start();
        }
        countDownLatch.await();
    }


    //用tomicLong
        static void testLongAdder(final int threadCount, final int times) throws InterruptedException {
            CountDownLatch countDownLatch = new CountDownLatch(threadCount);
            LongAdder longAdder = new LongAdder();
            for(int i = 0; i < threadCount; i++){
                new Thread(()->{
                    for(int j=0;j<times;j++){
                        longAdder.add(1);
                    }
                    countDownLatch.countDown();
                }).start();
            }
            countDownLatch.await();
        }

}
